package com.smh.demo1.a15;

import org.aopalliance.aop.Advice;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.*;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author shiminghui
 * @date 2025/4/18 10:45
 * @description: TODO
 */
public class A15Application {

    public static void main(String[] args) throws NoSuchMethodException {

        // 适配器模式

        Method[] methods =
                MyAspect.class.getMethods();

        AspectInstanceFactory aspectInstanceFactory = new SingletonAspectInstanceFactory(new MyAspect());

        ArrayList<Advisor> advisors = new ArrayList<>();

        for (Method method : methods) {
            if (method.isAnnotationPresent(Before.class)) {
                // 获取注解里面的value值
                String value = method.getAnnotation(Before.class).value();
                // 创建切点
                AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
                pointcut.setExpression(value);
                // 创建通知
                Advice advice = new AspectJMethodBeforeAdvice(method, pointcut, aspectInstanceFactory);

                // 创建切面
                DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
                advisors.add(advisor);
            } else if (method.isAnnotationPresent(After.class)) {
                // 获取注解里面的value值
                String value = method.getAnnotation(After.class).value();
                // 创建切点
                AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
                pointcut.setExpression(value);
                // 创建通知
                Advice advice = new AspectJAfterAdvice(method, pointcut, aspectInstanceFactory);

                // 创建切面
                DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
                advisors.add(advisor);
            } else if (method.isAnnotationPresent(AfterReturning.class)) {
                // 获取注解里面的value值
                String value = method.getAnnotation(AfterReturning.class).value();
                // 创建切点
                AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
                pointcut.setExpression(value);
                // 创建通知
                Advice advice = new AspectJAfterReturningAdvice(method, pointcut, aspectInstanceFactory);
                // 创建切面
                DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
                advisors.add(advisor);
            } else if (method.isAnnotationPresent(AfterThrowing.class)) {
                // 获取注解里面的value值
                String value = method.getAnnotation(AfterThrowing.class).value();
                // 创建切点
                AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
                pointcut.setExpression(value);
                // 创建通知
                Advice advice = new AspectJAfterThrowingAdvice(method, pointcut, aspectInstanceFactory);
                // 创建切面
                DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
                advisors.add(advisor);
            } else if (method.isAnnotationPresent(Around.class)) {
                // 获取注解里面的value值
                String value = method.getAnnotation(Around.class).value();
                // 创建切点
                AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
                pointcut.setExpression(value);
                // 创建通知
                Advice advice = new AspectJAroundAdvice(method, pointcut, aspectInstanceFactory);
                // 创建切面
                DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
                advisors.add(advisor);
            }
        }

        for (Advisor advisor : advisors) {
            System.out.println(advisor);
        }
        System.out.println("----------------------------------------------------------------");
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(new Target());
        proxyFactory.addAdvisors(advisors);

        Method method = Target.class.getMethod("read", int.class);

        List<Object> advices = proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(method, Target.class);
        for (Object advice : advices) {
            System.out.println(advice);
        }


    }

    @Aspect
    static class MyAspect {
        @Before("execution(* read(..))")
        public void before() {
            System.out.println("before");
        }

        @Before("execution(* read(..))")
        public void before1() {
            System.out.println("before1");
        }

        @After("execution(* read(..))")
        public void after() {
            System.out.println("after");
        }

        @Around("execution(* read(..))")
        public Object around(ProceedingJoinPoint pjp) {
            System.out.println("around");
            try {
                return pjp.proceed();
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        }

        @AfterReturning("execution(* read(..))")
        public void afterReturning() {
            System.out.println("afterReturning");
        }

        @AfterThrowing("execution(* read(..))")
        public void afterThrowing() {
            System.out.println("afterThrowing");
        }

    }

    static class Target {
        public void read(int sum) {
            System.out.println("read");
        }
    }

}
